#include "FileManager.h"

#include "CalculateManager.h"

// 构造函数
FileManager::FileManager() :
	outFileMutex{ 0 },
	stop_loop(false)
{

}

// 析构函数
FileManager::~FileManager()
{
	StopFileManagerThreads();
}

FileManager fileManager;

/**
 * @brief 将电压数据存储到 新文件 CSV文件中
 *
 * @param chNo 通道号
 * @param voltageList 电压数据数组
 * @param data_Length 电压数据的长度
 * @param filePath 文件路径
 */
int FileManager::storeDataToCSV(uint16_t chNo, double* voltageList, uint32_t data_Length, const std::string& filePath)
{
	// 将 chNo 转换为目录名
	std::string dirName = "CH" + std::to_string(chNo);
	std::filesystem::path dirPath = std::filesystem::path(filePath).parent_path() / dirName;

	// 提前检查并创建目录
	if (!std::filesystem::exists(dirPath))
	{
		std::filesystem::create_directories(dirPath);
		std::cout << "Directory created: " << dirPath << std::endl;
	}

	// 获取当前时间并格式化为文件名的一部分
	auto now = std::chrono::system_clock::now();
	auto duration = now.time_since_epoch();
	auto milliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(duration);
	std::time_t now_c = std::chrono::system_clock::to_time_t(now);
	std::tm timeStruct;
	localtime_s(&timeStruct, &now_c);

	// 格式化时间
	std::ostringstream timeStream;
	timeStream << std::put_time(&timeStruct, "%y%m%d_%H%M%S")
		<< std::setw(3) << std::setfill('0') << milliseconds.count() % 1000;

	// 拼接文件名
	std::ostringstream fileNameStream;
	fileNameStream << "CH" << chNo << "_" << timeStream.str() << ".csv";
	std::filesystem::path fullPath = dirPath / fileNameStream.str();

	// 使用 mutex 对文件操作进行保护，确保多线程安全
	std::lock_guard<std::mutex> lock(outFileMutex[chNo]);

	// 打开文件进行写入
	// 创建局部文件流
	std::ofstream outFile;
	outFile.open(fullPath, std::ios::binary | std::ios::app);
	//std::ofstream& outFileRef = outFile[chNo];
	std::ofstream& outFileRef = outFile;
	if (outFileRef.is_open())
	{
		outFileRef.close(); // 如果文件已打开，先关闭
	}

	outFileRef.open(fullPath, std::ios::app);
	if (!outFileRef.is_open())
	{
		std::cerr << "无法打开文件: " << fullPath << std::endl;
		return -1; // 返回错误码
	}

	// 写入表头
	outFileRef << "CH" << chNo << "_Voltage" << std::endl;

	// 将数据分批处理，每批最多 16384 个数据
	uint32_t batchSize = 16384;
	for (uint32_t i = 0; i < data_Length; i += batchSize) {
		// 替代 std::min，使用三元运算符来确保不会越界
		for (uint32_t j = i; j < (i + batchSize < data_Length ? i + batchSize : data_Length); ++j) {
			outFileRef << voltageList[j] << '\n';  // 将数据写入文件
		}
	}

	// 确保数据写入并关闭文件
	outFileRef.flush();
	outFileRef.close();

	return 0;
}

/**
 * @brief 将电压数据存储到 新文件 dat文件中
 *
 * @param chNo 通道号
 * @param voltageList 电压数据数组
 * @param data_Length 电压数据的长度
 * @param filePath 文件路径
 */
 /*
 int FileManager::storeDataToDat(uint16_t chNo, double* voltageList, uint32_t data_Length, const std::string& filePath)
 {
	 // 将 chNo 转换为目录名
	 std::string dirName = "CH" + std::to_string(chNo);
	 std::filesystem::path dirPath = std::filesystem::path(filePath).parent_path() / dirName;

	 // 提前检查并创建目录
	 if (!std::filesystem::exists(dirPath))
	 {
		 std::filesystem::create_directories(dirPath);
		 std::cout << "Directory created: " << dirPath << std::endl;
	 }

	 // 获取当前时间并格式化为文件名的一部分
	 auto now = std::chrono::system_clock::now();
	 auto duration = now.time_since_epoch();
	 auto milliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(duration);
	 std::time_t now_c = std::chrono::system_clock::to_time_t(now);
	 std::tm timeStruct;
	 localtime_s(&timeStruct, &now_c);

	 // 格式化时间
	 std::ostringstream timeStream;
	 timeStream << std::put_time(&timeStruct, "%y%m%d_%H%M%S")
		 << std::setw(3) << std::setfill('0') << milliseconds.count() % 1000;

	 // 拼接文件名
	 std::ostringstream fileNameStream;
	 fileNameStream << "CH" << chNo << "_" << timeStream.str() << ".dat";
	 std::filesystem::path fullPath = dirPath / fileNameStream.str();

	 // 使用 mutex 对文件操作进行保护，确保多线程安全
	 std::lock_guard<std::mutex> lock(outFileMutex[chNo]);

	 // 打开文件进行写入
	 std::ofstream& outFileRef = outFile[chNo];
	 if (outFileRef.is_open())
	 {
		 outFileRef.close(); // 如果文件已打开，先关闭
	 }

	 outFileRef.open(fullPath, std::ios::binary | std::ios::app);
	 if (!outFileRef.is_open())
	 {
		 std::cerr << "无法打开文件: " << fullPath << std::endl;
		 return -1; // 返回错误码
	 }

	 // 写入数据（每个数据以 double 类型存储，直接按二进制写入）
	 for (int i = 0; i < data_Length; ++i)
	 {
		 outFileRef.write(reinterpret_cast<const char*>(&voltageList[i]), sizeof(double));
	 }

	 // 确保数据写入并关闭文件
	 outFileRef.flush();
	 outFileRef.close();

	 return 0;
 }
 */
int FileManager::storeDataToDat(uint16_t chNo, double* voltageList, uint32_t data_Length, const std::string& filePath)
{
	// 将 chNo 转换为目录名
	std::string dirName = "CH" + std::to_string(chNo);
	std::filesystem::path dirPath = std::filesystem::path(filePath).parent_path() / dirName;

	// 提前检查并创建目录
	if (!std::filesystem::exists(dirPath))
	{
		std::filesystem::create_directories(dirPath);
		std::cout << "Directory created: " << dirPath << std::endl;
	}

	// 获取当前时间并格式化为文件名的一部分
	auto now = std::chrono::system_clock::now();
	auto duration = now.time_since_epoch();
	auto milliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(duration);
	std::time_t now_c = std::chrono::system_clock::to_time_t(now);
	std::tm timeStruct;
	localtime_s(&timeStruct, &now_c);

	// 格式化时间
	std::ostringstream timeStream;
	timeStream << std::put_time(&timeStruct, "%y%m%d_%H%M%S")
		<< std::setw(3) << std::setfill('0') << milliseconds.count() % 1000;

	// 拼接文件名
	std::ostringstream fileNameStream;
	fileNameStream << "CH" << chNo << "_" << timeStream.str() << ".dat";
	std::filesystem::path fullPath = dirPath / fileNameStream.str();

	// 使用 mutex 对文件操作进行保护，确保多线程安全
	std::lock_guard<std::mutex> lock(outFileMutex[chNo]);

	// 创建局部文件流
	std::ofstream outFile;
	outFile.open(fullPath, std::ios::binary | std::ios::app);
	if (!outFile.is_open())
	{
		std::cerr << "无法打开文件: " << fullPath << std::endl;
		return -1; // 返回错误码
	}

	// 写入数据（每个数据以 double 类型存储，直接按二进制写入）
	for (uint32_t i = 0; i < data_Length; ++i)
	{
		outFile.write(reinterpret_cast<const char*>(&voltageList[i]), sizeof(double));
	}

	// 确保数据写入并关闭文件
	outFile.flush();
	outFile.close();

	return 0;
}

/**
 * @brief 将 .dat 文件 转为 .csv
 *
 * @param chNo 通道号
 * @param filePath 文件路径
 */
int FileManager::convertDatToCSV(uint16_t chNo, const std::string& datFilePath)
{
	// 生成对应的 CSV 文件名
	std::filesystem::path datPath(datFilePath);
	std::filesystem::path csvFilePath = datPath.replace_extension(".csv");

	// 打开二进制 .dat 文件
	std::ifstream datFile(datFilePath, std::ios::binary);
	if (!datFile.is_open())
	{
		std::cerr << "无法打开二进制文件: " << datFilePath << std::endl;
		return -1; // 返回错误码
	}

	// 获取文件大小并计算数据长度
	datFile.seekg(0, std::ios::end);
	size_t fileSize = datFile.tellg();
	datFile.seekg(0, std::ios::beg);

	// 每个数据项的大小是 double 类型的大小
	int data_Length = static_cast<int>(fileSize / sizeof(double));

	// 打开 CSV 文件进行写入
	std::ofstream csvFile(csvFilePath);
	if (!csvFile.is_open())
	{
		std::cerr << "无法打开 CSV 文件: " << csvFilePath << std::endl;
		return -2; // 返回错误码
	}

	// 写入表头
	csvFile << "CH" << chNo << "_Voltage" << std::endl;

	// 将数据按批次处理，每批最多 16384 个数据
	int batchSize = 16384;
	double voltageData;

	for (int i = 0; i < data_Length; i += batchSize)
	{
		// 替代 std::min，使用三元运算符来确保不会越界
		for (int j = i; j < (i + batchSize < data_Length ? i + batchSize : data_Length); ++j)
		{
			// 从二进制文件中读取数据并写入 CSV 文件
			datFile.read(reinterpret_cast<char*>(&voltageData), sizeof(double));
			if (datFile.gcount() == sizeof(double))
			{
				csvFile << voltageData << '\n';  // 将数据写入文件
			}
			else
			{
				std::cerr << "读取数据时出错！" << std::endl;
				return -3; // 返回错误码
			}
		}
	}

	// 关闭文件
	datFile.close();
	csvFile.close();

	std::cout << "CSV 文件已生成: " << csvFilePath << std::endl;
	return 0;
}

// 启动所有线程
void FileManager::StartFileManagerThreads() {
	for (int chNo = 1; chNo <= MAX_CHANNEL_NUMBER; ++chNo) {
		FileManager_threads.push_back(std::thread(&FileManager::FileManagerTask, this, chNo));
	}
}

// 停止所有线程
void FileManager::StopFileManagerThreads() {
	stop_loop.store(true);  // 设置 stop_loop 为 true，线程退出条件
	for (auto& t : FileManager_threads) {
		if (t.joinable()) {
			t.join();  // 等待所有线程完成
		}
	}
}

// 每个线程的任务
void FileManager::FileManagerTask(int chNo) {
	while (!stop_loop.load()) {  // 使用 stop_loop 来控制线程的停止
		auto& voltageQueue = *VoltageQueue[chNo - 1];  // 获取当前通道的 VoltageQueue
		if (!voltageQueue.isEmpty()) {
			processVoltageData(chNo, "D:/");
		}

		// 控制线程执行间隔
		std::this_thread::sleep_for(std::chrono::milliseconds(100));  // 每 100ms 执行一次
	}
}

void FileManager::processVoltageData(uint16_t chNo, const std::string& filePath) {

	// 获取通道索引
	uint16_t channelIndex = chNo - 1;

	// 创建VoltageDataWrapper 数组，大小为 MAX_CHANNEL_NUMBER
	std::vector<VoltageDataWrapper> VoltageData(MAX_CHANNEL_NUMBER);

	// 临时的电压数据 结构体 初始化
	VoltageData[channelIndex].Data = std::make_unique<double[]>(MAX_POINT_COUNT / 2);
	if (VoltageData[channelIndex].Data == nullptr) {
		// 处理内存分配失败的情况
		std::cout << "Channel" << (int)chNo << " 电压数据结构体初始化错误" << std::endl;
		return;
	}

	// 从队列取出数据
	auto& voltageQueue = *VoltageQueue[channelIndex];
	if (!voltageQueue.isEmpty()) {
		// 提取数据包
		//VoltageData[channelIndex] = voltageQueue.pop();
		VoltageData[channelIndex] = std::move(*voltageQueue.pop());
	}
	else {
		std::cerr << "队列为空，无法获取数据" << std::endl;
		return;
	}

	// 调用storeDataToDat函数将数据存储到文件
	fileManager.storeDataToDat(chNo, &VoltageData[channelIndex].Data[0], VoltageData[channelIndex].DataSize, filePath);
}



